package lv.imho.server.services;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import lv.imho.client.model.DataSourceTransferObject;
import lv.imho.client.model.DataTransferObject;
import lv.imho.client.services.DataService;
import lv.imho.server.model.Data;
import lv.imho.server.model.DataSource;
import lv.imho.utils.Utils;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * Provides access to back-end database data.
 * 
 * @author Igors Gulbinskis
 */
public class DataServiceImpl extends RemoteServiceServlet implements DataService {

	private static final long serialVersionUID = 1L;

	@Override
	public Boolean saveData(DataTransferObject dataTransferObject) {	
		PersistenceManager pm = PersistenceService.getFactory().getPersistenceManager();
		try {
			pm.makePersistent(Utils.getData(dataTransferObject));			
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			pm.close();
		}
	}
	
	@Override
	public Boolean saveDataSource(DataSourceTransferObject dataSourceTransferObject) {
		PersistenceManager pm = PersistenceService.getFactory().getPersistenceManager();
		try {
			pm.makePersistent(Utils.getDataSource(dataSourceTransferObject));			
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			pm.close();
		}
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<DataTransferObject> getData(List<DataSourceTransferObject> dataSourceTransferObjects, Date date) {
		PersistenceManager pm = PersistenceService.getFactory().getPersistenceManager();
		try {
			Calendar startDate = Calendar.getInstance();
			startDate.setTime(date);
			startDate.set(Calendar.HOUR, 0);
			startDate.set(Calendar.MINUTE, 0);
			startDate.set(Calendar.SECOND, 1);
			
			Calendar endDate = Calendar.getInstance();
			endDate.setTime(date);
			endDate.set(Calendar.HOUR, 23);
			endDate.set(Calendar.MINUTE, 59);
			endDate.set(Calendar.SECOND, 59);
			
			Query query = pm.newQuery("select from " + Data.class.getName());
			query.setFilter("time >= startDate && time <= endDate");
			query.declareParameters("java.util.Date startDate, java.util.Date endDate");			
			List<Data> result = (List<Data>) query.execute(startDate.getTime(), endDate.getTime());
						
			List<DataTransferObject> filteredDataTransferObjects = new ArrayList<DataTransferObject>();
			label: for (Data data : result) {
				for (DataSourceTransferObject dataSource : dataSourceTransferObjects) {
					if (data.getDataSourceId().longValue() == dataSource.getId().longValue()) {
						filteredDataTransferObjects.add(Utils.getDataTransferObject(data, dataSource));
						continue label;
					}
				}
			}		
			return filteredDataTransferObjects;
		} finally {
			pm.close();
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<DataSourceTransferObject> getDataSources() {		
		PersistenceManager pm = PersistenceService.getFactory().getPersistenceManager();
		try {
			Query query = pm.newQuery("select from " + DataSource.class.getName());
			List<DataSource> result = (List<DataSource>) query.execute();
			
			/* can cause some exception on first run */
			List<DataSourceTransferObject> dataSourceTransferObjects = new ArrayList<DataSourceTransferObject>();
			for (DataSource dataSource : result) {
				dataSourceTransferObjects.add(Utils.getDataSourceTransferObject(dataSource));
			}				
			return dataSourceTransferObjects;
		} finally {
			pm.close();
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public Boolean exists(DataTransferObject data) {
		PersistenceManager pm = PersistenceService.getFactory().getPersistenceManager();
		try {
			Query query = pm.newQuery("select from " + Data.class.getName());
			query.setFilter("dataSourceId == _dataSourceId && heading == _heading");
			query.declareParameters("java.lang.String _dataSourceId, java.lang.String _heading");			
			List<Object> result = (List<Object>) query.execute(data.getDataSource().getId(), data.getHeading());
			
			return !(result == null || result.isEmpty());
		} finally {
			pm.close();
		}
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public Boolean exists(DataSourceTransferObject dataSource) {
		PersistenceManager pm = PersistenceService.getFactory().getPersistenceManager();
		try {
			Query query = pm.newQuery("select from " + DataSource.class.getName());
			query.setFilter("name == _name");
			query.declareParameters("java.lang.String _name");			
			List<Object> result = (List<Object>) query.execute(dataSource.getName());
			
			return !(result == null || result.isEmpty());
		} finally {
			pm.close();
		}
	}

}
